using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.AssetGraph;

namespace IQIGame.Onigao.Game.Editors
{
    [Serializable]
    [CustomAssetImporterConfigurator(typeof(Texture), "Texture(固定平台，必须用这个)", "setting.png")]
    public class FixPlatformTextureImporterConfigurator : IAssetImporterConfigurator
    {
        [SerializeField] private bool m_overwritePackingTag;
        [SerializeField] private bool m_overwriteSpriteSheet;
        [SerializeField] private SerializableMultiTargetString m_customPackingTagTemplate;

        [SerializeField] private List<PlatformTextureSetting> m_platformSettings = new List<PlatformTextureSetting>();
        private int currentPlatformIndex = 0;

        public enum PlatformType
        {
            Standalone = 0,
            Android,
            iPhone,
        }

        private static readonly string[] PlatformTypeNames = Enum.GetNames(typeof(PlatformType));
        private static readonly string[] kMaxTextureSizeStrings = new string[] { "32", "64", "128", "256", "512", "1024", "2048", "4096", "8192" };
        private static readonly int[] kMaxTextureSizeValues = new int[] { 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 };

        private static readonly string[] kMobileCompressionQualityOptions = new string[]
        {
            "Fast",
            "Normal",
            "Best"
        };

        [Serializable]
        public class PlatformTextureSetting
        {
            public PlatformType platformType;
            public int maxTextureSize = 2048;
            public int compressionQuality = 50;
            public TextureImporterFormat textureFormat = TextureImporterFormat.RGBA32;
            public TextureImporterFormat noAlphaTextureFormat = TextureImporterFormat.RGB24;
        }



        public void Initialize(ConfigurationOption option)
        {
            m_overwritePackingTag = option.overwritePackingTag;
            m_overwriteSpriteSheet = option.overwriteSpriteSheet;
            m_customPackingTagTemplate = option.customPackingTagTemplate;
        }

        public bool IsModified(AssetImporter referenceImporter, AssetImporter importer, BuildTarget target, string group)
        {
            var r = referenceImporter as TextureImporter;
            var t = importer as TextureImporter;
            if (t == null || r == null)
            {
                throw new AssetGraphException($"Invalid AssetImporter assigned for {importer.assetPath}");
            }
            return !IsEqual(t, r, GetTagName(target, group));
        }

        public void Configure(AssetImporter referenceImporter, AssetImporter importer, BuildTarget target, string group)
        {
            var r = referenceImporter as TextureImporter;
            var t = importer as TextureImporter;
            if (t == null || r == null)
            {
                throw new AssetGraphException($"Invalid AssetImporter assigned for {importer.assetPath}");
            }
            OverwriteImportSettings(t, r, GetTagName(target, group));
        }

        public void OnInspectorGUI(AssetImporter referenceImporter, BuildTargetGroup target, Action onValueChanged)
        {
            var importer = referenceImporter as TextureImporter;
            if (importer == null)
            {
                return;
            }

            if (importer.textureType == TextureImporterType.Sprite)
            {
                using (new EditorGUILayout.VerticalScope(GUI.skin.box))
                {

                    GUILayout.Label("Sprite Settings");
                    GUILayout.Space(4f);
                    var bSpriteSheet = EditorGUILayout.ToggleLeft("Configure Sprite Mode", m_overwriteSpriteSheet);
                    var bPackingTag = EditorGUILayout.ToggleLeft("Configure Sprite Packing Tag", m_overwritePackingTag);

                    if (bSpriteSheet != m_overwriteSpriteSheet ||
                       bPackingTag != m_overwritePackingTag)
                    {
                        m_overwriteSpriteSheet = bSpriteSheet;
                        m_overwritePackingTag = bPackingTag;
                        onValueChanged();
                    }

                    if (m_overwritePackingTag)
                    {
                        if (m_customPackingTagTemplate == null)
                        {
                            m_customPackingTagTemplate = new SerializableMultiTargetString();
                        }

                        var val = m_customPackingTagTemplate.DefaultValue;

                        var newValue = EditorGUILayout.TextField("Packing Tag", val);
                        if (newValue != val)
                        {
                            m_customPackingTagTemplate.DefaultValue = newValue;
                            onValueChanged();
                        }
                    }
                    EditorGUILayout.HelpBox(
                        "You can configure packing tag name with \"*\" to include group name in your sprite tag.",
                        MessageType.Info);
                }
            }


            if (RefreshTexturePlatformSetting())
            {
                onValueChanged();
            }

            // 扩展自定义贴图的平台设置
            EditorGUI.BeginChangeCheck();
            using (new EditorGUILayout.VerticalScope(GUI.skin.box))
            {
                GUILayout.Label("Texture Platform Settings");
                GUILayout.Space(4f);
                currentPlatformIndex = GUILayout.Toolbar(currentPlatformIndex, PlatformTypeNames);
                var currentPlatform = m_platformSettings[currentPlatformIndex];
                // 绘制平台贴图设置
                currentPlatform.maxTextureSize = EditorGUILayout.IntPopup("Max Size", currentPlatform.maxTextureSize, kMaxTextureSizeStrings, kMaxTextureSizeValues);

                int num2 = 1;
                bool flag3 = currentPlatform.compressionQuality == 0;
                if (flag3)
                {
                    num2 = 0;
                }
                else
                {
                    bool flag4 = currentPlatform.compressionQuality == 100;
                    if (flag4)
                    {
                        num2 = 2;
                    }
                }
                switch (EditorGUILayout.Popup("Compressor Quality", num2, kMobileCompressionQualityOptions))
                {
                    case 0:
                        currentPlatform.compressionQuality = 0;
                        break;
                    case 1:
                        currentPlatform.compressionQuality = 50;
                        break;
                    case 2:
                        currentPlatform.compressionQuality = 100;
                        break;
                    default:
                        currentPlatform.compressionQuality = 50;
                        break;
                }

                currentPlatform.textureFormat = (TextureImporterFormat)EditorGUILayout.EnumPopup("RGBA_Format", currentPlatform.textureFormat);
                currentPlatform.noAlphaTextureFormat = (TextureImporterFormat)EditorGUILayout.EnumPopup("RGB_Format(no alpha)", currentPlatform.noAlphaTextureFormat);
            }
            if (EditorGUI.EndChangeCheck())
            {
                onValueChanged();
            }


        }

        private bool RefreshTexturePlatformSetting()
        {
            //刷新列表
            if (m_platformSettings.Count == PlatformTypeNames.Length)
            {
                bool allequal = true;
                for (int i = 0; i < m_platformSettings.Count; ++i)
                {
                    if (m_platformSettings[i].platformType != (PlatformType)i)
                    {
                        allequal = false;
                    }
                }
                if (allequal)
                {
                    return false;
                }
            }
            var newList = new List<PlatformTextureSetting>();
            for (int i = 0; i < PlatformTypeNames.Length; ++i)
            {
                var found = false;
                foreach (var p in m_platformSettings)
                {
                    if (p.platformType == (PlatformType)i)
                    {
                        newList.Add(p);
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    var newPlatform = new PlatformTextureSetting()
                    {
                        platformType = (PlatformType)i,
                    };
                    switch (newPlatform.platformType)
                    {
                        case PlatformType.Standalone:
                            newPlatform.textureFormat = TextureImporterFormat.DXT5;
                            newPlatform.noAlphaTextureFormat = TextureImporterFormat.DXT1;
                            break;
                        case PlatformType.Android:
                            newPlatform.textureFormat = TextureImporterFormat.ASTC_6x6;
                            newPlatform.noAlphaTextureFormat = TextureImporterFormat.ASTC_6x6;
                            break;
                        case PlatformType.iPhone:
                            newPlatform.textureFormat = TextureImporterFormat.ASTC_6x6;
                            newPlatform.noAlphaTextureFormat = TextureImporterFormat.ASTC_6x6;
                            break;
                    }
                    newList.Add(newPlatform);

                }
            }
            m_platformSettings = newList;
            return true;
        }

        private string GetTagName(BuildTarget target, string groupName)
        {
            return m_customPackingTagTemplate[target].Replace("*", groupName);
        }

        private void ApplySpriteTag(BuildTarget target, IEnumerable<PerformGraph.AssetGroups> incoming)
        {

            foreach (var ag in incoming)
            {
                foreach (var groupKey in ag.assetGroups.Keys)
                {
                    var assets = ag.assetGroups[groupKey];
                    foreach (var asset in assets)
                    {

                        if (asset.importerType == typeof(UnityEditor.TextureImporter))
                        {
                            var importer = AssetImporter.GetAtPath(asset.importFrom) as TextureImporter;

                            importer.spritePackingTag = GetTagName(target, groupKey);
                            importer.SaveAndReimport();
                            asset.TouchImportAsset();
                        }
                    }
                }
            }
        }
        private bool IsEqual(TextureImporter target, TextureImporter reference, string tagName)
        {
            // UnityEditor.TextureImporter.textureFormat' is obsolete: 
            // `textureFormat is not longer accessible at the TextureImporter level
            if (target.textureType != reference.textureType)
                return false;

            TextureImporterSettings targetSetting = new TextureImporterSettings();
            TextureImporterSettings referenceSetting = new TextureImporterSettings();

            target.ReadTextureSettings(targetSetting);
            reference.ReadTextureSettings(referenceSetting);

            // if m_overwriteSpriteSheet is false, following properties
            // should be ignored
            if (!m_overwriteSpriteSheet)
            {
                referenceSetting.spriteAlignment = targetSetting.spriteAlignment;
                referenceSetting.spriteBorder = targetSetting.spriteBorder;
                referenceSetting.spriteExtrude = targetSetting.spriteExtrude;
                referenceSetting.spriteMode = targetSetting.spriteMode;
                referenceSetting.spriteMeshType = targetSetting.spriteMeshType;
                referenceSetting.spritePivot = targetSetting.spritePivot;
                referenceSetting.spritePixelsPerUnit = targetSetting.spritePixelsPerUnit;
                referenceSetting.spriteTessellationDetail = targetSetting.spriteTessellationDetail;
            }

            if (!TextureImporterSettings.Equal(targetSetting, referenceSetting))
            {
                return false;
            }

            if (target.textureType == TextureImporterType.Sprite)
            {
                if (m_overwritePackingTag)
                {
                    if (!string.IsNullOrEmpty(tagName))
                    {
                        if (target.spritePackingTag != tagName)
                            return false;
                    }
                    else
                    {
                        if (target.spritePackingTag != reference.spritePackingTag)
                            return false;
                    }
                }

                if (m_overwriteSpriteSheet)
                {
                    if (target.spriteBorder != reference.spriteBorder)
                        return false;
                    if (target.spriteImportMode != reference.spriteImportMode)
                        return false;
                    if (target.spritePivot != reference.spritePivot)
                        return false;
                    if (target.spritePixelsPerUnit != reference.spritePixelsPerUnit)
                        return false;

                    var s1 = target.spritesheet;
                    var s2 = reference.spritesheet;

                    if (s1.Length != s2.Length)
                    {
                        return false;
                    }

                    for (int i = 0; i < s1.Length; ++i)
                    {
                        if (s1[i].alignment != s2[i].alignment)
                            return false;
                        if (s1[i].border != s2[i].border)
                            return false;
                        if (s1[i].name != s2[i].name)
                            return false;
                        if (s1[i].pivot != s2[i].pivot)
                            return false;
                        if (s1[i].rect != s2[i].rect)
                            return false;
                    }
                }
            }

            if (target.allowAlphaSplitting != reference.allowAlphaSplitting)
                return false;
            if (target.alphaIsTransparency != reference.alphaIsTransparency)
                return false;
            if (target.alphaSource != reference.alphaSource)
                return false;
            if (target.alphaTestReferenceValue != reference.alphaTestReferenceValue)
                return false;
            if (target.androidETC2FallbackOverride != reference.androidETC2FallbackOverride)
                return false;
            if (target.anisoLevel != reference.anisoLevel)
                return false;
            if (target.borderMipmap != reference.borderMipmap)
                return false;
            if (target.compressionQuality != reference.compressionQuality)
                return false;
            if (target.convertToNormalmap != reference.convertToNormalmap)
                return false;
            if (target.crunchedCompression != reference.crunchedCompression)
                return false;
            if (target.fadeout != reference.fadeout)
                return false;
            if (target.filterMode != reference.filterMode)
                return false;
            if (target.generateCubemap != reference.generateCubemap)
                return false;
            if (target.heightmapScale != reference.heightmapScale)
                return false;
            if (target.isReadable != reference.isReadable)
                return false;
            if (target.maxTextureSize != reference.maxTextureSize)
                return false;
            if (target.mipMapBias != reference.mipMapBias)
                return false;
            if (target.mipmapEnabled != reference.mipmapEnabled)
                return false;
            if (target.mipmapFadeDistanceEnd != reference.mipmapFadeDistanceEnd)
                return false;
            if (target.mipmapFadeDistanceStart != reference.mipmapFadeDistanceStart)
                return false;
            if (target.mipmapFilter != reference.mipmapFilter)
                return false;
            if (target.mipMapsPreserveCoverage != reference.mipMapsPreserveCoverage)
                return false;
            if (target.normalmapFilter != reference.normalmapFilter)
                return false;
            if (target.npotScale != reference.npotScale)
                return false;

            if (target.sRGBTexture != reference.sRGBTexture)
                return false;
            if (target.streamingMipmaps != reference.streamingMipmaps)
                return false;
            if (target.streamingMipmapsPriority != reference.streamingMipmapsPriority)
                return false;
            if (target.textureCompression != reference.textureCompression)
                return false;
            if (target.textureShape != reference.textureShape)
                return false;
            if (target.wrapMode != reference.wrapMode)
                return false;
            if (target.wrapModeU != reference.wrapModeU)
                return false;
            if (target.wrapModeV != reference.wrapModeV)
                return false;
            if (target.wrapModeW != reference.wrapModeW)
                return false;

            var refDefault = reference.GetDefaultPlatformTextureSettings();
            var impDefault = target.GetDefaultPlatformTextureSettings();
            if (!CompareImporterPlatformSettings(refDefault, impDefault))
                return false;

            //foreach (var g in NodeGUIUtility.SupportedBuildTargetGroups)
            //{
            //    var platformName = BuildTargetUtility.TargetToAssetBundlePlatformName(g, BuildTargetUtility.PlatformNameType.TextureImporter);

            //    var impSet = reference.GetPlatformTextureSettings(platformName);
            //    var targetImpSet = target.GetPlatformTextureSettings(platformName);
            //    if (!CompareImporterPlatformSettings(impSet, targetImpSet))
            //        return false;
            //}

            var hasAlpha = target.DoesSourceTextureHaveAlpha()
                || reference.alphaSource == TextureImporterAlphaSource.FromGrayScale;
            for (int i = 0; i < PlatformTypeNames.Length; i++)
            {
                var platformName = PlatformTypeNames[i];
                if (i >= m_platformSettings.Count)
                {
                    break;
                }
                var platformTextureSetting = m_platformSettings[i];
                TextureImporterPlatformSettings importerSettings = target.GetPlatformTextureSettings(platformName);
                if (importerSettings.maxTextureSize != platformTextureSetting.maxTextureSize)
                {
                    return false;
                }
                if (importerSettings.compressionQuality != platformTextureSetting.compressionQuality)
                {
                    return false;
                }
                var format = hasAlpha ? platformTextureSetting.textureFormat : platformTextureSetting.noAlphaTextureFormat;
                if (importerSettings.format != format)
                {
                    return false;
                }
                if (!importerSettings.overridden)
                {
                    return false;
                }
            }


            return true;
        }

        private void OverwriteImportSettings(TextureImporter target, TextureImporter reference, string tagName)
        {
            target.textureType = reference.textureType;

            var dstSettings = new TextureImporterSettings();
            var srcSettings = new TextureImporterSettings();

            target.ReadTextureSettings(srcSettings);
            reference.ReadTextureSettings(dstSettings);

            if (!m_overwriteSpriteSheet)
            {
                dstSettings.spriteAlignment = srcSettings.spriteAlignment;
                dstSettings.spriteBorder = srcSettings.spriteBorder;
                dstSettings.spriteExtrude = srcSettings.spriteExtrude;
                dstSettings.spriteMode = srcSettings.spriteMode;
                dstSettings.spriteMeshType = srcSettings.spriteMeshType;
                dstSettings.spritePivot = srcSettings.spritePivot;
                dstSettings.spritePixelsPerUnit = srcSettings.spritePixelsPerUnit;
                dstSettings.spriteTessellationDetail = srcSettings.spriteTessellationDetail;
            }

            target.SetTextureSettings(dstSettings);

            if (m_overwriteSpriteSheet)
            {
                target.spritesheet = reference.spritesheet;
            }

            // some unity version do not properly copy properties via TextureSettings,
            // so also perform manual copy
            target.allowAlphaSplitting = reference.allowAlphaSplitting;
            target.alphaIsTransparency = reference.alphaIsTransparency;
            target.alphaSource = reference.alphaSource;
            target.alphaTestReferenceValue = reference.alphaTestReferenceValue;
            target.androidETC2FallbackOverride = reference.androidETC2FallbackOverride;
            target.anisoLevel = reference.anisoLevel;
            target.borderMipmap = reference.borderMipmap;
            target.compressionQuality = reference.compressionQuality;
            target.convertToNormalmap = reference.convertToNormalmap;
            target.crunchedCompression = reference.crunchedCompression;
            target.fadeout = reference.fadeout;
            target.filterMode = reference.filterMode;
            target.generateCubemap = reference.generateCubemap;
            target.heightmapScale = reference.heightmapScale;
            target.isReadable = reference.isReadable;
            target.maxTextureSize = reference.maxTextureSize;
            target.mipMapBias = reference.mipMapBias;
            target.mipmapEnabled = reference.mipmapEnabled;
            target.mipmapFadeDistanceEnd = reference.mipmapFadeDistanceEnd;
            target.mipmapFadeDistanceStart = reference.mipmapFadeDistanceStart;
            target.mipmapFilter = reference.mipmapFilter;
            target.mipMapsPreserveCoverage = reference.mipMapsPreserveCoverage;
            target.normalmapFilter = reference.normalmapFilter;
            target.npotScale = reference.npotScale;
            target.sRGBTexture = reference.sRGBTexture;
            target.streamingMipmaps = reference.streamingMipmaps;
            target.streamingMipmapsPriority = reference.streamingMipmapsPriority;
            target.textureCompression = reference.textureCompression;
            target.textureShape = reference.textureShape;
            target.wrapMode = reference.wrapMode;
            target.wrapModeU = reference.wrapModeU;
            target.wrapModeV = reference.wrapModeV;
            target.wrapModeW = reference.wrapModeW;

            if (m_overwritePackingTag)
            {
                if (!string.IsNullOrEmpty(tagName))
                {
                    target.spritePackingTag = tagName;
                }
                else
                {
                    target.spritePackingTag = reference.spritePackingTag;
                }
            }

            var defaultPlatformSetting = reference.GetDefaultPlatformTextureSettings();
            target.SetPlatformTextureSettings(defaultPlatformSetting);

            //foreach (var g in NodeGUIUtility.SupportedBuildTargetGroups)
            //{
            //    var platformName = BuildTargetUtility.TargetToAssetBundlePlatformName(g, BuildTargetUtility.PlatformNameType.TextureImporter);
            //    var impSet = reference.GetPlatformTextureSettings(platformName);
            //    target.SetPlatformTextureSettings(impSet);
            //}

            var hasAlpha = target.DoesSourceTextureHaveAlpha()
                || reference.alphaSource == TextureImporterAlphaSource.FromGrayScale;

            for (int i = 0; i < PlatformTypeNames.Length; i++)
            {
                var platformName = PlatformTypeNames[i];
                if (i >= m_platformSettings.Count)
                {
                    break;
                }
                var platformTextureSetting = m_platformSettings[i];
                TextureImporterPlatformSettings importerSettings = target.GetPlatformTextureSettings(platformName);
                importerSettings.maxTextureSize = platformTextureSetting.maxTextureSize;
                importerSettings.compressionQuality = platformTextureSetting.compressionQuality;
                importerSettings.format = hasAlpha ? platformTextureSetting.textureFormat : platformTextureSetting.noAlphaTextureFormat;
                importerSettings.overridden = true;
                target.SetPlatformTextureSettings(importerSettings);
            }
        }

        bool CompareImporterPlatformSettings(TextureImporterPlatformSettings c1, TextureImporterPlatformSettings c2)
        {
            if (c1.allowsAlphaSplitting != c2.allowsAlphaSplitting)
                return false;
            if (c1.androidETC2FallbackOverride != c2.androidETC2FallbackOverride)
                return false;
            if (c1.compressionQuality != c2.compressionQuality)
                return false;
            if (c1.crunchedCompression != c2.crunchedCompression)
                return false;
            if (c1.format != c2.format)
                return false;
            if (c1.maxTextureSize != c2.maxTextureSize)
                return false;
            if (c1.name != c2.name)
                return false;
            if (c1.overridden != c2.overridden)
                return false;
            if (c1.resizeAlgorithm != c2.resizeAlgorithm)
                return false;
            if (c1.textureCompression != c2.textureCompression)
                return false;

            return true;
        }

    }
}
